package dst.ass2.ejb.management;

import java.math.BigDecimal;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import dst.ass2.ejb.management.interfaces.IPriceManagementBean;
import dst.ass2.ejb.model.IPrice;
import dst.ass2.ejb.model.impl.Price;

@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Singleton
public class PriceManagementBean implements IPriceManagementBean {
	
	@PersistenceContext
	private EntityManager entityManager;
	private ConcurrentSkipListSet<IPrice> prices=new ConcurrentSkipListSet<IPrice>();
	
	private final static Logger LOGGER = Logger.getLogger(PriceManagementBean.class.getName());
	
	
	@SuppressWarnings("unchecked")
	@PostConstruct					//after Construction load the Prices in list
    public void postConstruct() {
        Query query = entityManager.createQuery("SELECT p FROM Price p");
        if(query!=null){
        	prices.addAll(query.getResultList());
        	LOGGER.info("Number of Prices in PriceManagementBean after Initialization: "+ prices.size());
        }
        else{
        	LOGGER.info("No Prices found in PriceManagementBean after Initialization!!");
        }
    }

	
	@Override				//http://docs.oracle.com/javaee/6/tutorial/doc/gipvi.html
	@Lock(LockType.READ)   //Annotate a singleton’s business or timeout method with @Lock(LockType.READ) if the method can be concurrently accessed, or shared, with many clients
	public BigDecimal getPrice(Integer nrOfHistoricalTasks) {
		Price actual = new Price();  //construct new Price
		actual.setNrOfHistoricalTasks(nrOfHistoricalTasks+1);  //set the actual number of Historical Tasks +1 because we use lower
		BigDecimal retPriceValue=null;
		  
	    IPrice retPrice=prices.lower(actual);  //returns the greatest element in this set strictly less than the given element //Comparable on nrOfHistoricalTasks 
	    
	    if (retPrice == null) {					//if return is null
	    	retPriceValue=new BigDecimal(0);	//then price value is 0
	    }
	    else{
	    	retPriceValue=retPrice.getPrice();	//else use Price
	    }
	    
	    LOGGER.info("getPrice in PriceManagementBean"+ retPriceValue);
	    
	    return retPriceValue;
	}


	@Override  
	@Lock(LockType.WRITE)    //Annotate the business or timeout method with @Lock(LockType.WRITE) if the singleton session bean should be locked to other clients while a client is calling that method
	public void setPrice(Integer nrOfHistoricalTasks, BigDecimal price) {
		Price actPrice = new Price();								//initialize Price step
		actPrice.setNrOfHistoricalTasks(nrOfHistoricalTasks);
		actPrice.setPrice(price);

		if (!prices.contains(actPrice)) {   //if this Price Bean is not in List
			prices.add(actPrice);				//add it
			entityManager.persist(actPrice);   //persist it
			LOGGER.info("setPrice in PriceManagementBean added a new Price");
		}
		else{
			LOGGER.info("setPrice in PriceManagementBean Price already in List");
		}
	}
	
	@Override
	public void clearCache() {
		 prices=new ConcurrentSkipListSet<IPrice>();
		 LOGGER.info("clearCache in PriceManagementBean done");
	}
}
